/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package umat.beans;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import java.io.Serializable;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import org.primefaces.event.NodeSelectEvent;
import org.primefaces.model.TreeNode;

/**
 *
 * @author Tudor
 */
@ManagedBean(name = "tree")
@SessionScoped
public class Tree implements Serializable {

    private final Node backBone;    //hidden by primefaces, not used by us
    private Node root;              //actual root
    private Node selectedNode;      //reference to the selected node in the GUI
    private String name;            //stores the name of the node in the GUI

    /**
     * 
     */
    public Tree() {
        backBone = new Node("Back bone node", null);
        root = new Node("Root", backBone);
        selectedNode = root;
        root.setSelected(true);
    }
    public Tree(Tree t){
        backBone=t.getBackBone();
        root=t.getRoot();
    }
    /**
     * 
     * @return the back bone node used by primefaces to render the tree
     */
    public Node getBackBone() {
        return backBone;
    }

    /**
     * 
     * @return the root of the tree
     */
    public Node getRoot() {
        return root;
    }

    /**
     * 
     * @return the current value of the variable connected to the text field for the node addition in the GUI
     */
    public String getName() {
        return name;
    }

    /**
     * 
     * @return the selected node
     */
    public Node getSelectedNode() {
        return selectedNode;
    }

    /**
     * 
     * @param selectedNode
     */
    public void setSelectedNode(Node selectedNode) {
        this.selectedNode = selectedNode;
    }

    /**
     * 
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * This method displays the selected node in a FacesMessage
     */
    public void displaySelectedSingle() {
        if (selectedNode != null) {
            if (((Node) selectedNode).getFields().isEmpty()) {
                FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, "Selected", selectedNode.getData().toString() + ", no fields");
                FacesContext.getCurrentInstance().addMessage(null, message);
            } else {
                FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, "Selected", selectedNode.getData().toString() + " " + ((Node) selectedNode).getFields().size() + " fields");
                FacesContext.getCurrentInstance().addMessage(null, message);
            }
        }
    }

    /**
     * This method handles the GUI node selection event
     * @param event
     */
    public void onNodeSelect(NodeSelectEvent event) {
        if (((Node) event.getTreeNode()) != selectedNode) {
            selectedNode = (Node) event.getTreeNode();    
        }
    }

    /**
     * Deletes the selected node and removes it from the parents child list.
     * It will not delete the root of the tree, instead, it will clear all its
     * fields and children
     */
    public void deleteNode() {
        if (!selectedNode.equals(root)) {
            printMessage(selectedNode.toString() + " deleted!");
            selectedNode.getChildren().clear();
            selectedNode.getParent().getChildren().remove(selectedNode);
            selectedNode.setParent(null);
            selectedNode = null;
        } else {
            printMessage("Cannot delete root!");
            selectedNode.getChildren().clear();
        }
    }

    /**
     * Adds a node to the selected node using the value in the 'name' variable
     */
    public void addNode() {
        //to be modified later
        if (selectedNode != null) {
            Node n = new Node(name, selectedNode);
            //printMessage("Node added:" + name + " to " + selectedNode.toString());
            name = "";
        } else {
            //printMessage("No node selected");
        }
    }

    /**
     * 
     * @param message message to be printed
     */
    public void printMessage(String message) {
        FacesMessage m = new FacesMessage(FacesMessage.SEVERITY_INFO, "Selected", message);
        FacesContext.getCurrentInstance().addMessage(null, m);
    }

    /**
     * Clears all the information in the tree and leaves the root node
     */
    public void reset() {
        System.out.println("Resetting root's children");
        resetNode((Node) root);
    }

    /**
     * Recursive function to clear the nodes and their fields
     * @param n 
     */
    private void resetNode(Node n) {
        System.out.println("Resetting " + n.toString());
        n.getFields().clear();
        System.out.println("Fields cleared");
        if (!n.getChildren().isEmpty()) {
            for (TreeNode c : n.getChildren()) {
                resetNode((Node) c);
            }
        }
        n.getChildren().clear();
        n = null;

    }

    /**
     * Edit the selected nodes name
     */
    public void editName(){
        printMessage("Node "+selectedNode.getData().toString()+" edited to "+name);
        selectedNode.setData(name);
        name=null;
    }
    
    @Override
    public String toString() {
        //should be revised
        return root.toString();
    }
}
